﻿using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections.ObjectModel;
using corpus_platform.Data;
using System.Diagnostics;

namespace corpus_platform.ViewModels
{
    public class RootViewModel : BindableBase, INodeStructure, INodeContainer
    {
        public RootViewModel()
        {
        }
        private int counter = 0;
        private Dictionary<int, List<FrameViewModel>> frameInstanceMarkerMap = new();

        public StructureType Type => StructureType.Root;

        public RootViewModel Root => this;

        public bool AllowDrag { get; set; } = false;

        private ObservableCollection<INodeStructure> storage = new();
        public ObservableCollection<INodeStructure> Storage
        {
            get { return storage; }
            set { SetProperty(ref storage, value); }
        }
        
        public Result add(INodeStructure structure)
        {
            if (structure.Type != StructureType.Root)
            {
                this.Storage.Add(structure);
                return Result.Success;
            }
            return Result.Failure;
        }

        public void remove(INodeStructure structure)
        {
            if (structure.Type != StructureType.Root)
            {
                bool is_contain = this.Storage.Contains(structure);
                bool res = this.Storage.Remove(structure);
            }
        }

        public void ChangeParentTo(INodeContainer structure)
        {
            throw new NotImplementedException();
        }

        public void registerFrameInstance(FrameViewModel frameInstance)
        {
            frameInstance.Marker = counter;
            frameInstanceMarkerMap.Add(counter, new List<FrameViewModel>() { frameInstance });
            counter++;
        }

        public bool canDeregisterFrameInstance(FrameViewModel frameInstance)
        {
            if (frameInstance.Marker == null)
            {
                return true;
            }
            else
            {
                if (frameInstanceMarkerMap[(int)frameInstance.Marker].Count > 1)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }

        public void deregisterFrameInstance(FrameViewModel frameInstance)
        {
            int marker = (int)frameInstance.Marker;
            frameInstanceMarkerMap.Remove(marker);
        }

        public void copyFrameInstance(FrameViewModel frameInstance)
        {
            FrameViewModel newFrameInstance = frameInstance.getClone();
            frameInstanceMarkerMap[(int)frameInstance.Marker].Add(newFrameInstance);
            Storage.Add(newFrameInstance);
        }

        public void removeFrameInstance(FrameViewModel frameInstance)
        {
            int marker = (int)frameInstance.Marker;
            frameInstanceMarkerMap[marker].Remove(frameInstance);
            if (frameInstanceMarkerMap[marker].Count == 0)
            {
                frameInstanceMarkerMap.Remove(marker);
            }
        }

        public object GetValue(MetaInformation metaInformation)
        {
            List<object> frameInstances = new();
            foreach (INodeStructure structure in Storage)
            {
                if (structure.Type == StructureType.Frame)
                {
                    FrameViewModel frame = (FrameViewModel)structure;
                    if (frame.IsInstance)
                    {
                        frameInstances.Add(frame.GetValue(metaInformation));
                    }
                }
            }
            return frameInstances.ToArray();
        }

        public void SweepStorageToRoot()
        {
            throw new NotImplementedException();
        }

        public void Clear()
        {
            this.frameInstanceMarkerMap.Clear();
            this.Storage.Clear();
        }
    }
}
